package rad.framework.jboss;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
import javax.security.auth.login.Configuration;

import org.jboss.ejb3.embedded.BrainlessContext;
import org.jboss.security.auth.callback.SecurityAssociationHandler;
import org.jboss.security.auth.login.XMLLoginConfigImpl;
import org.jboss.security.plugins.JaasSecurityManager;
import org.jboss.util.CachePolicy;

/**
 * 
 * @author boudyacho
 * 
 */
public class JaasSecurityManagerService {
	private static final String SECURITY_MGR_PATH = "java:/jaas";

	private static Map<String, JaasSecurityManager> cache = new HashMap<String, JaasSecurityManager>();

	private Hashtable initialContextProperties;

	public JaasSecurityManagerService() {

	}

	public void setInitialContextProperties(Hashtable initialContextProperties) {
		this.initialContextProperties = initialContextProperties;
	}

	private InitialContext getInitialContext() throws NamingException {
		if (initialContextProperties != null)
			return new InitialContext(initialContextProperties);
		else
			return new InitialContext();
	}

	public void start() throws Exception {
		XMLLoginConfigImpl configuration = new XMLLoginConfigImpl();
		configuration.setConfigResource("login-config.xml");
		configuration.loadConfig();

		Configuration.setConfiguration(configuration);

		Context ctx = getInitialContext();

		String factoryName = SecurityDomainObjectFactory.class.getName();
		Reference ref = new Reference(
				"nl.wolfc.embedded.security.plugins.JaasSecurityManager",
				factoryName, null);
		ctx.rebind(SECURITY_MGR_PATH, ref);
	}

	private static JaasSecurityManager getSecurityManager(String name) {
		JaasSecurityManager manager = cache.get(name);
		if (manager != null) {
			// log.info("cache hit");
			return manager;
		}
		synchronized (cache) {
			if (manager != null)
				return manager;

			manager = new JaasSecurityManager(name,
					new SecurityAssociationHandler());
			manager.setCachePolicy(new MockCachePolicy());
			cache.put(name, manager);
		}
		return manager;
	}

	public static class SecurityDomainObjectFactory implements ObjectFactory {
		public Object getObjectInstance(Object obj, Name name, Context nameCtx,
				Hashtable environment) throws Exception {
			return new BrainlessContext() {
				public Object lookup(Name name) throws NamingException {
					return lookup(name.get(0));
				}

				public Object lookup(String name) throws NamingException {
					return getSecurityManager(name);
				}
			};
		}
	}

	public static class MockCachePolicy implements CachePolicy {

		public void create() throws Exception {
		}

		public void destroy() {
		}

		public void flush() {
		}

		public Object get(Object arg0) {
			return null;
		}

		public void insert(Object arg0, Object arg1) {
		}

		public Object peek(Object arg0) {
			return null;
		}

		public void remove(Object arg0) {
		}

		public int size() {
			return 0;
		}

		public void start() throws Exception {
		}

		public void stop() {
		}
	}
}
